#SingleInstance force
CoordMode, Mouse, Screen
detecthiddenwindows, on
; Length of a cycle
cycleLength = 50

; Amount of cycles to wait before engaging the hotcorner
delayBeforeActivating = 4


actions=mDesktop desktop 1|mDesktop desktop 2|mDesktop desktop 3|mDesktop desktop 4|Lock Computer|Start Screensaver

StringSplit, actions_a, actions , |



if !fileexist("Hotcorners.ini")
{
	IniWrite, 4, Hotcorners.ini, Settings, delayBeforeActivating
	;IniWrite, !1, Hotcorners.ini, Settings, hotkeyTopLeft
	;IniWrite, !2, Hotcorners.ini, Settings, hotkeyTopRight
	;IniWrite, !3, Hotcorners.ini, Settings, hotkeyBottomLeft
	;IniWrite, !4, Hotcorners.ini, Settings, hotkeyBottomRight
	IniWrite , !^h, Hotcorners.ini, Settings, hotkey
	IniWrite, mDesktop desktop 1, Hotcorners.ini, Settings, actionTopLeft
	IniWrite, mDesktop desktop 2, Hotcorners.ini, Settings, actionTopRight
	IniWrite, mDesktop desktop 3, Hotcorners.ini, Settings, actionBottomLeft
	IniWrite, mDesktop desktop 4, Hotcorners.ini, Settings, actionBottomRight
	
	
}

IniRead, delayBeforeActivating, Hotcorners.ini, Settings, delayBeforeActivating, 4
;IniRead, hotkeyTopLeft, Hotcorners.ini, Settings, hotkeyTopLeft, !1
;IniRead, hotkeyTopRight, Hotcorners.ini, Settings, hotkeyTopRight, !2
;IniRead, hotkeyBottomLeft, Hotcorners.ini, Settings, hotkeyBottomLeft, !3
;IniRead, hotkeyBottomRight, Hotcorners.ini, Settings, hotkeyBottomRight, !4

IniRead, actionTopLeft, Hotcorners.ini, Settings, actionTopLeft
IniRead, actionTopRight, Hotcorners.ini, Settings, actionTopRight
IniRead, actionBottomLeft, Hotcorners.ini, Settings, actionBottomLeft
IniRead, actionBottomRight, Hotcorners.ini, Settings, actionBottomRight
IniRead, hotkey, Hotcorners.ini, Settings, hotkey


Menu,tray,NoStandard
Menu,tray,icon,Hotcorners.ico
Menu,tray,add,Hide,hide
Menu,tray,add,
Menu,tray,add,About,About
Menu,tray,add,Settings,Settings
Menu,tray,add,Exit,cleanup

Hotkey , %hotkey% , unhide
Hotkey , %hotkey% , off

delayBeforeActivating_temp = 0


Loop
{
	cornerWaiting = 0
	cornerActive = 0
	
	MouseGetPos, mouseX, mouseY
	SysGet, VirtualScreenWidth, 78
	SysGet, VirtualScreenHeight, 79
	screenWidth := VirtualScreenWidth - 1
	screenHeight := VirtualScreenHeight - 1



	; Top-left corner
	if mouseX = 0
	{
		if mouseY = 0
		{
			delayBeforeActivating_temp++
			cornerWaiting = 1
		}
	}

	; Top-right corner
	if mouseX = %screenWidth%
	{
		if mouseY = 0
		{
			delayBeforeActivating_temp++
			cornerWaiting = 2
		}
	}

	; Bottom-left corner
	if mouseX = 0
	{
		if mouseY = %screenHeight%
		{
			delayBeforeActivating_temp++
			cornerWaiting = 3
		}
	}

	; Bottom-right corner
	if mouseX = %screenWidth%
	{
		if mouseY = %screenHeight%
		{
			delayBeforeActivating_temp++
			cornerWaiting = 4
		}
	}

	if delayBeforeActivating_temp >= %delayBeforeActivating%
	{
		delayBeforeActivating_temp = 0
		
		if cornerWaiting > 0
		{
			cornerActive = %cornerWaiting%

			if cornerActive = 1
			{
				doaction("TopLeft")
			}
			else if cornerActive = 2
			{
				doaction("TopRight")
			}
			else if cornerActive = 3
			{
				doaction("BottomLeft")
			}
			else if cornerActive = 4
			{
				doaction("BottomRight")
			}
		}
	}
	
	if cornerWaiting = 0
	{
		delayBeforeActivating_temp = 0
	}

	;ToolTip, %delayBeforeActivating_temp% - %cornerWaiting% - %cornerActive% - mouse: (%mouseX%`,%mouseY%) - screen: (%screenWidth%`,%screenHeight%) - raw: (%A_ScreenWidth%`,%A_ScreenHeight%) - %cycleLength%`,%cycleLength_raw%`,%delayBeforeActivating%

	Sleep, %cycleLength%
}





; GUI for user configurable hotkeys

settings:
	
	cycleLength_raw := cycleLength * delayBeforeActivating
	
	gui 7: add,text,,Delay in milliseconds before activating a hotcorner (default: 200)
	gui 7: add,edit,w80 number vcycleLength_raw, %cycleLength_raw%
	
	; Top left
	
	default:=pickdefault("TopLeft")
	
	
	gui 7: add,text,,Select an action for the top left corner:
	Gui 7: Add, DropDownList, vactionTopLeft, %default%


	; Top right

	default:=pickdefault("TopRight")
	
	gui 7: add,text,,Select an action for the top right corner:
	Gui 7: Add, DropDownList, vactionTopRight, %default%

	; Bottom left

	default:=pickdefault("BottomLeft")
	
	
	gui 7: add,text,,Select an action for the bottom left corner:
	Gui 7: Add, DropDownList, vactionbottomleft, %default%

	; Bottom right
	default:=pickdefault("BottomRight")
	
	gui 7: add,text,,Select an action for the bottom right corner:
	gui 7: Add, DropDownList, vactionbottomright, %default%
	
	gui 7: add,text,,Select a hotkey to unhide Hotcorners' tray icon.
	gui 7: add,hotkey,vnewunhidehotkey, %hotkey%


	gui 7: add,button,gsavesettings,Save	
	gui 7: show,,Settings
return


7guiclose:
	gui 7: destroy
return



hide:
	menu ,tray,NoIcon
	Hotkey , %hotkey% , on
	StringReplace , DisplayKey, hotkey, ^ , Control%a_space% , All
	StringReplace , DisplayKey, DisplayKey, ! , Alt%a_space% , All
	StringReplace , DisplayKey, DisplayKey, + ,Shift%a_space% , All
	msgbox The icon will now be hidden, press %DisplayKey% to unhide.
return

unhide:
	menu ,tray,Icon
	Hotkey , %hotkey% , off
return



pickdefault(corner)
{
	global
	
	
	thiscorneraction:=action%corner%
	dropdown=
	
	Loop %actions_a0%
	{
		element := actions_a%A_Index%  ; A_Index is a built-in variable.
		if element=%thiscorneraction%
		{
			dropdown=%dropdown%%element%||
		}
		else
		{
			dropdown=%dropdown%%element%|
		}
	}
	return dropdown
}

doaction(corner)
{
	global
	thiscorneraction:=action%corner%

	if thiscorneraction=mDesktop desktop 1
		IPC_Send( WinExist("mDesktop_api"), "SwitchToDesktop1", 100)
	else if thiscorneraction=mDesktop desktop 2
		IPC_Send( WinExist("mDesktop_api"), "SwitchToDesktop2", 100)
	else if thiscorneraction=mDesktop desktop 3
		IPC_Send( WinExist("mDesktop_api"), "SwitchToDesktop3", 100)
	else if thiscorneraction=mDesktop desktop 4
		IPC_Send( WinExist("mDesktop_api"), "SwitchToDesktop4", 100)
	else if thiscorneraction=Lock Computer
		Run, rundll32.exe user32.dll`,LockWorkStation
	else if thiscorneraction=Start Screensaver
		SendMessage, 0x112, 0xF140, 0,, Program Manager
		
	return
}



savesettings:
	gui 7: submit
	gui 7: destroy
		
	if not newunhidehotkey=hotkey
	{
		Hotkey , %hotkey% , off
		hotkey=%newunhidehotkey%
		Hotkey , %hotkey% , unhide
		Hotkey , %hotkey% , off
		IniWrite, %hotkey%, Hotcorners.ini, Settings, hotkey
	}
	
	delayBeforeActivating := round(cycleLength_raw / 50)
	IniWrite, %delayBeforeActivating%, Hotcorners.ini, Settings, delayBeforeActivating
	
	IniWrite, %actionTopLeft%, Hotcorners.ini, Settings, actionTopLeft
	IniWrite, %actionTopRight%, Hotcorners.ini, Settings, actionTopRight
	IniWrite, %actionBottomLeft%, Hotcorners.ini, Settings, actionBottomLeft
	IniWrite, %actionBottomRight%, Hotcorners.ini, Settings, actionBottomRight

	

return

CleanUp:
ExitApp
return

About:
MsgBox,,About, Hotcorners Version: 1.1`n`nCreated by Polatrite`nCopyright 2010`n`nIndependent game developer and software programmer`nVisit my site for more tools and games!`nhttp://www.polatrite.com/`n`nModifications by Jason Stallings.`n`ncode.google.com/p/hotcorners



#r::
Reload
return

IPC_Send(Hwnd, Data="", Port=100, DataSize="") {
	static WM_COPYDATA = 74, INT_MAX=2147483647
	if Port not between 0 AND %INT_MAX%
		return A_ThisFunc "> Port number is not in a positive integer range: " Port

	if (DataSize = "")
		 DataSize := StrLen(Data)+1, pData := &Data, Port := -Port			;use negative port for textual messages
	else pData := Data

	VarSetCapacity(COPYDATA, 12)
	 , NumPut(Port,		COPYDATA, 0)
	 , NumPut(DataSize, COPYDATA, 4)             
	 , NumPut(pData,	COPYDATA, 8)             
	
	Gui, +LastFound	 
   	SendMessage, WM_COPYDATA, WinExist(), &COPYDATA,, ahk_id %Hwnd%
	return ErrorLevel="FAIL" ? false : true
}

IPC_SetHandler( Handler ){
	static WM_COPYDATA = 74

	if !IsFunc( Handler )
		return A_ThisFunc "> Invalid handler: " Handler
	
	OnMessage(WM_COPYDATA, "IPC_onCopyData")
	IPC_onCopyData(Handler, "")
}


IPC_onCopyData(WParam, LParam) {
	static Handler
	if Lparam =
		return  Handler := WParam
		
	port := NumGet(Lparam+0, 0, "Int"), data := NumGet(Lparam+8)
	if port < 0
		 data := DllCall("MulDiv", "Int", data, "Int",1, "Int", 1, "str"), port := -port
	else size := NumGet(LParam+4)

	%handler%(WParam, data, port, size)
	return 1
}

/* 
 Group: About 
 	o IPC AHK & .Net library ver 2.6 by majkinetor.
	o Fixes for 64b systems of IPC.cs made by Lexikos.
	o MSDN Reference: <http://msdn.microsoft.com/en-us/library/ms649011(VS.85).aspx>
	o Licenced under GNU GPL <http://creativecommons.org/licenses/GPL/2.0/>
 */

